<template>
  <Dialog
    ref="dialog"
    :fullscreen="true"
    title="账号配置"
    :content="content"
    :appendToBody="true"
  >
    <div class="box" v-loading="loading">
      <!-- 左侧动态菜单 -->
      <el-menu
        :default-active="activeMenuIndex"
        class="el-menu-vertical-demo"
        @select="handleMenuSelect"
      >
        <el-menu-item
          v-for="(item, index) in menuItems"
          :key="index"
          :index="item"
        >
          {{ item }}
        </el-menu-item>
      </el-menu>
      <!-- 右侧内容 -->
      <div class="editer-box">
        <JsonEditor
          @save-json="handleSaveJson"
          :languageDataList="languageDataList"
        />
      </div>
    </div>
  </Dialog>
</template>
<script setup lang="tsx">
import Dialog from '@/components/Dialog/Dialog.vue';
import { ref, onMounted } from 'vue';
import JsonEditor from '@/components/JsonEditor/index.vue';
import isArray from 'lodash';
import { ElMessage } from 'element-plus';
import api from '@/modules'; // 默认配置项
const {
  getConfigDataApi,
  saveConfigDataApi,
  getConfigListApi,
  LanguagePackApi,
} = api;
interface DialogInstance {
  openChange: () => void;
  closeChange: () => void;
}
const content = ref('');
const dialog = ref<DialogInstance | null>(null); // 指定 dialog 类型为 DialogInstance 或 null
const loading = ref(false);
const fieldMappings = ref({}); // 使用 ref 存储字段映射表
const languageDataList = ref({});
const configData = ref([]);
// storeid
const storeId = ref(null);
// JsonEditor 的配置项
// let defaultJson = reactive({});
// 动态菜单项
const menuItems = ref([]);
// 当前选中的菜单项的索引
const activeMenuIndex = ref('');
// 处理左侧菜单选择
const handleMenuSelect = async (configName: string) => {
  activeMenuIndex.value = configName;
  try {
    // 清空 defaultJson 的内容
    clearObject(languageDataList.value);

    const params = {
      storeId: storeId.value,
      configName,
    };

    const { data } = await getConfigDataApi(params);
    configData.value = JSON.parse(data[configName]);

    if (configData != null) {
      // 合并数据并转换字段
      const mergedData = Object.assign({}, configData.value); // 合并数据
      const translatedConfigData = convertToChinese(
        fieldMappings.value,
        mergedData
      ); // 转换字段
      languageDataList.value = translatedConfigData;
    } else {
      Object.assign(languageDataList.value, {});
    }
  } catch (error) {
    console.error('Error in handleMenuSelect:', error);
  }
};
// 清空响应式对象的内容
const clearObject = (obj: any) => {
  Object.keys(obj).forEach((key) => {
    delete obj[key];
  });
};
// 保存 JSON 数据
const handleSaveJson = async (json: any) => {
  // 假设json是一个对象，而不是字符串
  const originalData = convertKeys(json, invertMapping(fieldMappings.value));
  loading.value = true;
  const params = {
    storeId: storeId.value,
    configName: activeMenuIndex.value,
    data: JSON.stringify(originalData),
  };
  const res = await saveConfigDataApi(params);
  if (res.code == 20000) {
    ElMessage.success('修改成功');
  }
  // dialog.value!.closeChange();
  loading.value = false;
};
// 获取配置key
const getConfigList = async () => {
  loading.value = true;
  const { data } = await getConfigListApi({
    type: 'store',
    storeId: storeId.value,
  });
  if (isArrayWithLength(data)) {
    await handleMenuSelect(data[0]); // 默认选中第一个菜单项
    menuItems.value = data;
  }
  loading.value = false;
};
// 判断是否为数组和有长度
const isArrayWithLength = (value: any) => {
  return isArray(value) && value.length > 0;
};
// 打开弹窗
const openchange = async (val: any) => {
  content.value = val.name;
  storeId.value = val.storeId;
  dialog.value!.openChange();
  await getConfigList();
};
// 字段转换函数
const convertToChinese = (mappings: Record<string, string>, data: any): any => {
  if (Array.isArray(data)) {
    return data.map((item) => convertToChinese(mappings, item)); // 递归处理数组
  } else if (typeof data === 'object' && data !== null) {
    let result: Record<string, any> = {};
    for (let key in data) {
      const translatedKey = mappings[key] || key; // 如果映射表中有对应中文名称，则替换
      result[translatedKey] = convertToChinese(mappings, data[key]); // 递归处理每个字段值
    }
    return result;
  }
  return data; // 如果是基本数据类型，直接返回
};

// 定义映射关系类型
type Mapping = { [key: string]: string };

/**
 * 递归遍历对象或数组，并转换其中的所有键名
 * @param obj - 要转换的对象或数组
 * @param mapping - 键名映射关系对象，key 为原键名，value 为新键名
 * @returns 转换后的新对象或数组
 */
function convertKeys(obj: any, mapping: Mapping): any {
  if (Array.isArray(obj)) {
    return obj.map((item) => convertKeys(item, mapping));
  } else if (obj !== null && typeof obj === 'object') {
    const newObj: { [key: string]: any } = {};
    for (const key in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, key)) {
        // 如果映射中存在该键，则替换，否则保持原键
        const newKey = mapping[key] || key;
        newObj[newKey] = convertKeys(obj[key], mapping);
      }
    }
    return newObj;
  }
  // 不是对象或数组，直接返回原值
  return obj;
}

const language = async () => {
  const data = await LanguagePackApi();
  if (data.code == 20000) {
    fieldMappings.value = data.data; // 更新映射表
  }
};

// 更换对象的key和value
function invertMapping(obj: Mapping): Mapping {
  const inverted: Mapping = {};
  for (const key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      const value = obj[key];
      inverted[value] = key;
    }
  }
  return inverted;
}

onMounted(() => {
  language();
});

defineExpose({
  openchange,
});
</script>

<style scoped lang="scss">
.box {
  display: flex;
  gap: 20px;
}
/* 左右布局间距调整 */
.el-menu-vertical-demo {
  width: 200px;
  height: calc(100vh - 360px);
  //   border-right: none !important;
}
.editer-box {
  width: 100%;
}
.custom-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 20px;
  border-bottom: 1px solid #ebeef5;
}
</style>
